import requests
import json
import os
from datetime import datetime
import csv
import time
from fund.get_history_data import read_funds_from_yml_list
from my_const import MY_PREFER_FUND_YML_LIST, REALTIME_SLEEP_TIME, HISTORY_DIR

from util.log_util import get_the_logger
logger = get_the_logger(__name__)


def get_fund_realtime(fund_code):
    """
    获取基金实时估算数据（基于天天基金网）
    :param fund_code: 基金代码（如 000001）
    :return: 包含实时估算净值、涨跌幅等信息的字典
    """
    # 天天基金网的基金实时行情接口
    url = f"http://fundgz.1234567.com.cn/js/{fund_code}.js"
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
    }
    try:
        response = requests.get(url, headers=headers)
        # 处理返回的jsonp格式数据（去除前后的括号和多余字符）
        data_str = response.text.strip().lstrip("jsonpgz(").rstrip(");")
        data = json.loads(data_str)

        # 提取关键信息
        result = {
            "fund_code": data["fundcode"],
            "fund_name": data["name"],
            "estimated_net_value": data["gsz"],  # 实时估算净值
            "estimated_growth_rate": data["gszzl"],  # 估算涨跌幅
            "estimated_time": data["gztime"]  # 数据更新时间
        }
        return result
    except Exception as e:
        logger.error(f"Failed to get real-time of fund {fund_code}: {e}, the url is {url}")
        return None


def append_realtime_to_csv(fund_code):
    """
    适配无索引列的CSV：仅追加[净值日期,单位净值,日增长率]三列数据
    逻辑调整：
    - API日期 > CSV最后日期：直接追加
    - API日期 == CSV最后日期：删除CSV最后一行后追加（覆盖同日期数据）
    - API日期 < CSV最后日期：不追加
    
    :param fund_code: 基金代码（字符串）
    :return: 布尔值 + 提示信息（True=成功/无需追加，False=失败）
    """
    # ---------------------- 1. 获取并解析实时API数据 ----------------------
    try:
        realtime_data = get_fund_realtime(fund_code)
        if not realtime_data:
            return False, f"Failed to get real-time data of fund {fund_code}"
        csv_file_path = HISTORY_DIR / f"{fund_code}-daily.csv"

        # 解析API时间（格式："YYYY-MM-DD HH:MM"）
        api_time_str = realtime_data["estimated_time"]
        api_datetime = datetime.strptime(api_time_str, "%Y-%m-%d %H:%M")
        api_date = api_datetime.date()
        api_date_str = api_date.strftime("%Y-%m-%d")  # 净值日期
        
        # 解析估值数据（保留对应精度）
        estimated_net = float(realtime_data["estimated_net_value"])  # 单位净值
        growth_rate = float(realtime_data["estimated_growth_rate"])  # 涨跌幅（%，原格式）

    except Exception as e:
        return False, f"Failed to parse real-time API data of fund {fund_code} - {e}"


    # ---------------------- 2. 读取CSV最后一行（无索引列，仅三列） ----------------------
    file_exists = os.path.exists(csv_file_path)
    if not file_exists:
        return False, f"CSV file not found: {csv_file_path}"

    required_cols = ["净值日期", "单位净值", "日增长率"]  # 无索引列，表头仅三列

    with open(csv_file_path, 'r', encoding='utf-8-sig') as f:
        reader = csv.reader(f)
        # 读取所有行（含表头），后续删除最后一行时需用到
        all_rows = [row for row in reader]
        
        # 校验表头（all_rows[0]是表头）
        if not all_rows or all_rows[0] != required_cols:
            return False, f"CSV header mismatch. Expected: {required_cols}, Got: {all_rows[0] if all_rows else 'None'}"
        
        # 读取最后一行数据（判断是否有数据行）
        if len(all_rows) > 1:  # 至少有“表头+1行数据”
            last_data_row = all_rows[-1]  # 最后一行数据（非表头）
            try:
                csv_last_date_str = last_data_row[0]
                csv_last_date = datetime.strptime(csv_last_date_str, "%Y-%m-%d").date()
            except (IndexError, ValueError) as e:
                return False, f"CSV last row format error - {str(e)}"
        else:  # 只有表头，无数据行
            csv_last_date = None


    # ---------------------- 3. 日期对比，判断操作类型（追加/覆盖/跳过） ----------------------
    need_remove_last_row = False  # 标记是否需要删除最后一行

    if csv_last_date is None:  # CSV只有表头，无数据行
        reason = "CSV has header only, append first row"
    elif api_date > csv_last_date:  # API日期更新，直接追加
        reason = f"API date ({api_date_str}) is newer than CSV last date ({csv_last_date.strftime('%Y-%m-%d')}), append new row"
    elif api_date == csv_last_date:  # API日期相同，删除原最后一行后追加（覆盖）
        need_remove_last_row = True
        reason = f"API date ({api_date_str}) equals CSV last date, 1. remove old row, 2. append new row"
    else:  # API日期更旧，跳过
        reason = f"API date ({api_date_str}) is older than CSV last date ({csv_last_date.strftime('%Y-%m-%d')}), skip"
        return True, f"No need append - {reason}"


    # ---------------------- 4. 执行核心操作（删除最后一行→追加新行） ----------------------
    
    # 步骤1：若需删除最后一行，先重新写入CSV（去掉最后一行数据）
    if need_remove_last_row:
        try:
            # 保留“表头 + 除最后一行外的所有数据行”（all_rows[:-1]即去掉最后一行）
            rows_to_keep = all_rows[:-1]
            with open(csv_file_path, 'w', encoding='utf-8-sig', newline='') as f:
                writer = csv.writer(f)
                writer.writerows(rows_to_keep)  # 重新写入（覆盖原有内容）
        except Exception as e:
            return False, f"Failed to remove CSV last row - {str(e)}"
    
    # 步骤2：构建新行并追加（仅三列，无索引）
    new_row = [
        api_date_str,
        f"{estimated_net:.4f}",  # 基金净值保留4位小数
        f"{growth_rate:.2f}"      # 涨跌幅保留2位小数（与原CSV格式一致）
    ]
    
    try:
        with open(csv_file_path, 'a', encoding='utf-8-sig', newline='') as f:
            writer = csv.writer(f)
            writer.writerow(new_row)
        return True, f"Succeed to process row - {reason}"
    except Exception as e:
        return False, f"Failed to append row to CSV - {str(e)}"


def get_all_funds_realtime_and_save():
    """
    Get real-time estimated data for all funds and save to corresponding CSV files
    """
    # Get all fund codes
    fund_code_list, _ = read_funds_from_yml_list(MY_PREFER_FUND_YML_LIST)

    # Get real-time data for each fund and save to CSV
    for fund_code in fund_code_list:
        success, msg = append_realtime_to_csv(fund_code)
        logger.info(f"Fund {fund_code}: {success} -> {msg}")
        time.sleep(REALTIME_SLEEP_TIME)



if __name__ == "__main__":
    # fund_code = "017436"
    fund_code = "017091"

    # # case 1
    # realtime_data = get_fund_realtime(fund_code)
    #
    # if realtime_data:
    #     logger.info("基金实时估算信息：")
    #     for key, value in realtime_data.items():
    #         logger.info(f"{key}: {value}")

    # # case 2
    # success, msg = append_realtime_to_csv(fund_code)
    # logger.info(success)
    # logger.info(msg)

    # case 3: test all
    get_all_funds_realtime_and_save()